package lumis.doui.control.itempicker;

import lumis.doui.control.ControlContainer;
import lumis.doui.control.ControlException;
import lumis.doui.control.DataBoundControl;
import lumis.doui.control.IClientSideReadableControl;
import lumis.doui.control.IControl;
import lumis.portal.PortalException;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.servicecontainer.ServiceContainerUrl;
import lumis.portal.serviceinstance.ServiceInstanceConfig;
import lumis.portal.serviceinterface.IServiceInterfaceUrl;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.util.XmlUtil;

import org.w3c.dom.Node;

/**
 * Used to select an item from a large list. 
 * <br/>
 * This control contains three significant properties. The id of the field that it
 * represents, the id of that field that represents a user friendly name for the field
 * that it represents and finally an interface that is responsible for searching and 
 * selecting the item.
 * <br/>
 * The control renders a readonly user friendly name with a selection and clear icon beside
 * it.  When the user selects the selection icon the specified search interface is popped
 * passing the javascript function name that should be called to update the identifier and
 * friendly name of this control.
 * <br/>
 * <br/> 
 * Example use:
 * <xmp>
 * <control:lum_itemPicker id="userId" displayDataId="userName">
 * 		<searchInterfaceId>lumis.service.sample.selectusingsearch.selectUser</searchInterfaceId>
 * </control:lum_itemPicker>
 * </xmp>
 * <br/>
 * 
 * xml data available for xsl rendering:
 * <xmp>
 * <control dataId="userId" displayDataId="userName" id="userId.userId" sourceId="default" type="lum_itemPicker">
 * 	<searchInterfaceId>lumis.service.sample.selectusingsearch.selectUser</searchInterfaceId>
 * 	<control id="8A488A0F158A409701158A42522F0095" type="lum_requiredValueValidator" />
 * 	<data>
 * 		<item>
 * 			<id>00000000D00000000000000000000004</id>
 * 			<displayString>LumisPageCacheUser</displayString>
 * 		</item>
 * 		<openPopupScript><!-- javascript for opening a pop to select an item --></openPopupScript>
 * 		<selectItemFunction><!-- javascript function that is called by the pop to set the id and display name of the item selected --></selectItemFunction>
 * 		<clearItemScript><!-- javascript to clear the id and name selected --></clearItemScript>
 * 	</data>
 * </control>
 * </xmp>
 * 
 * @version $Revision: 11835 $ $Date: 2010-08-05 16:29:01 -0300 (Thu, 05 Aug 2010) $
 * @since 4.1.0
 */
public class ItemPickerControl extends DataBoundControl implements IClientSideReadableControl
{
	private String displayDataId = null;
	private String searchInterfaceId = null;
	private String displayName = null;

	public void init(Node controlDefinitionNode, ControlContainer controlContainer, IControl parentControl) throws PortalException
	{
		super.init(controlDefinitionNode, controlContainer, parentControl);

		setDisplayDataId(XmlUtil.readAttributeString("displayDataId", controlDefinitionNode, getDataId()));
		setSearchInterfaceId(XmlUtil.readNodeString("searchInterfaceId", controlDefinitionNode));
	}

	@Override
	public void buildSubControls() throws PortalException
	{
		super.buildSubControls();

		autoAddValidators();
	}

	@Override
	public void loadFromRequest() throws PortalException 
	{
		super.loadFromRequest();
		displayName = douiContext.getRequest().getParameter(getId()+"_name");
	}

	@Override
	protected void setValueFromSource() throws PortalException
	{
		super.setValueFromSource();
		
		displayName = this.getSource().getData().get(getDisplayDataId(), String.class);
	}

	@Override
	public void setRenderData() throws PortalException
	{
		super.setRenderData();

		Node dataNode = XmlUtil.addNode(controlDefinitionNode, "data");

		String itemId = getValue(String.class);
		StringBuilder dataItemXml = new StringBuilder();
		dataItemXml.append("<item>");
		if (itemId != null)
			dataItemXml.append("<id>" + XmlUtil.encodeXml(itemId) + "</id>");
		if (displayName != null)
			dataItemXml.append("<displayString>" + XmlUtil.encodeXml(displayName) + "</displayString>");
		dataItemXml.append("</item>");
		XmlUtil.addNodeFromXmlString(dataNode, dataItemXml.toString());

		String formName = controlContainer.getFormName();

		IServiceInterfaceUrl popupUrl = getPopupUrl();
		XmlUtil.addTextNode(dataNode, "openPopupScript", ((ServiceContainerUrl) popupUrl).getWindowOpen(douiContext.getTransaction()) + ";");
		XmlUtil.addTextNode(dataNode, "selectItemFunction", "function select_" + formName + "_" + getId().replace(".", "") + "(id, name) {document.forms['" + formName + "'].elements['" + getId()
				+ "'].value=id;document.forms['" + formName + "'].elements['" + getId() + "_name'].value=name;}");
		XmlUtil.addTextNode(dataNode, "clearItemScript", "document.forms['" + formName + "'].elements['" + getId() + "'].value='';document.forms['" + formName + "'].elements['" + getId()
				+ "_name'].value='';");
	}

	protected IServiceInterfaceUrl getPopupUrl() throws PortalException
	{
		IServiceInterfaceUrl popupUrl = douiContext.getResponse().createRenderURL();
		String searchInterfaceId = getSearchInterfaceId();
		boolean requiresServiceInstance = ManagerFactory.getServiceInterfaceManager().getServiceInterfaceConfig(searchInterfaceId,
				PortalTransactionFactory.getCurrentTransaction()).isServiceInstanceRequired();

		if (requiresServiceInstance)
		{
			String serviceInstanceId = XmlUtil.readAttributeOrNodeString(controlDefinitionNode, "serviceInstanceId");
			boolean addedServiceInstanceId = false;
			if (serviceInstanceId != null)
			{
				popupUrl.setRunTimeServiceInstanceId(serviceInstanceId);
				addedServiceInstanceId = true;
			}
			if (!addedServiceInstanceId)
			{
				ServiceInstanceConfig serviceInstanceConfig = douiContext.getRequest().getServiceInstanceConfig();
				if (serviceInstanceConfig != null)
				{
					popupUrl.setRunTimeServiceInstanceId(serviceInstanceConfig.getId());
					addedServiceInstanceId = true;
				}
			}
			if (!addedServiceInstanceId)
				throw new ControlException("STR_SERVICE_INSTANCE_NOT_FOUND");
		}

		popupUrl.setRunTimeServiceInterfaceId(searchInterfaceId);
		popupUrl.setParameter("callbackFunction", "select_" + controlContainer.getFormName() + "_" + getId().replace(".", ""));

		return popupUrl;
	}

	public String getDisplayDataId()
	{
		return displayDataId;
	}

	public void setDisplayDataId(String displayField)
	{
		this.displayDataId = displayField;
	}

	public String getSearchInterfaceId()
	{
		return searchInterfaceId;
	}

	public void setSearchInterfaceId(String searchInterfaceId)
	{
		if(searchInterfaceId.contains("."))
		{
			this.searchInterfaceId = searchInterfaceId;
		}
		else
		{
			this.searchInterfaceId = this.douiContext.getRequest().getServiceConfig().getId()+"."+searchInterfaceId;
		}
	}

	@Override
	protected void autoAddValidators() throws PortalException
	{
		if (!this.hasValidatorSubControls)
		{
			autoAddRequiredValueValidator();
		}
	}
}
